package com.yanqu.road.entity.autodata.hotpotjump;

import com.yanqu.road.utils.RandomHelper;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HotpotJumpMainRole {
    private HotpotJumpGrid grid;
    private int lv;
    private int exp;
    private Map<eHotpotJumpAttr, Integer> attrMap = new HashMap<>();

    private List<List<Integer>> skills = new ArrayList<>();

    public HotpotJumpMainRole() {
    }

    public HotpotJumpGrid getGrid() {
        return grid;
    }

    public void setGrid(HotpotJumpGrid grid) {
        this.grid = grid;
    }

    public int getLv() {
        return lv;
    }

    public void setLv(int lv) {
        this.lv = lv;
    }

    public int getExp() {
        return exp;
    }

    public void setExp(int exp) {
        this.exp = exp;
    }

    public Map<eHotpotJumpAttr, Integer> getAttrMap() {
        return attrMap;
    }

    public void setAttrMap(Map<eHotpotJumpAttr, Integer> attrMap) {
        this.attrMap = attrMap;
    }

    public List<List<Integer>> getSkills() {
        return skills;
    }

    public void setSkills(List<List<Integer>> skills) {
        this.skills = skills;
    }

    public HotpotJumpMainRole clone() {
        HotpotJumpMainRole clone = new HotpotJumpMainRole();
        clone.setGrid(this.grid.clone());
        clone.lv = this.lv;
        clone.exp = this.exp;
        clone.attrMap = new HashMap<>(this.attrMap);
        for (List<Integer> skill : this.skills) {
            clone.skills.add(new ArrayList<>(skill));
        }
        return clone;
    }

    /**
     * 根据属性计算伤害,不算暴击
     *
     * @return
     */
    public int calcJumpDamage(int distance, int specialSkillAdd, int combMulti) {
        Integer atk = attrMap.get(eHotpotJumpAttr.Atk);
        Integer atkMulti = attrMap.getOrDefault(eHotpotJumpAttr.AtkMulti, 0);
        Integer jumpAtkMulti = attrMap.getOrDefault(eHotpotJumpAttr.JumpAtkMulti, 0) * distance;//攻击距离增加攻击力
        Integer damageMulti = attrMap.getOrDefault(eHotpotJumpAttr.DamageMulti, 0);

        int damage = BigDecimal.valueOf(atk).multiply(BigDecimal.valueOf(1000 + atkMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(combMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 + jumpAtkMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 + damageMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 + specialSkillAdd).divide(BigDecimal.valueOf(1000)))
                .setScale(0, BigDecimal.ROUND_UP).intValue();
        return damage;
    }

    public int calcStationaryDamage(int stationaryAtkMulti, int specialSkillAdd) {
        Integer atk = attrMap.get(eHotpotJumpAttr.Atk);
        Integer atkMulti = attrMap.getOrDefault(eHotpotJumpAttr.AtkMulti, 0);

        int damage = BigDecimal.valueOf(atk).multiply(BigDecimal.valueOf(1000 + atkMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(stationaryAtkMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 + specialSkillAdd).divide(BigDecimal.valueOf(1000)))
                .setScale(0, BigDecimal.ROUND_UP).intValue();
        return damage;
    }

    /**
     * 算下是否暴击
     *
     * @return
     */
    public int calcTriggerCriDamage(RandomHelper randomHelper, int damage) {
        Integer rate = attrMap.getOrDefault(eHotpotJumpAttr.CriticalRate, 0);
        if (rate == 0) {
            return damage;
        }
        int randomValue = randomHelper.next(1000);
        if (randomValue < rate) {
            Integer criMulti = attrMap.getOrDefault(eHotpotJumpAttr.CriticalDamage, 0);
            int criDamage = BigDecimal.valueOf(damage).multiply(BigDecimal.valueOf(2000 + criMulti).divide(BigDecimal.valueOf(1000))).setScale(0, BigDecimal.ROUND_UP).intValue();
            return criDamage;
        } else {
            return damage;
        }
    }

    /**
     * 计算被打伤害
     *
     * @param unit
     * @return
     */
    public int calcHurtValue(HotpotJumpUnit unit, boolean isBoss, int skillValue) {
        Integer hurtReduce = attrMap.getOrDefault(eHotpotJumpAttr.HurtReduce, 0);
        Integer bossHurtReduce = 0;
        if (isBoss) {
            bossHurtReduce = attrMap.getOrDefault(eHotpotJumpAttr.BossHurtReduce, 0);
        }
        int value = BigDecimal.valueOf(unit.getAtk()).multiply(BigDecimal.valueOf(1000 - hurtReduce).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(skillValue).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 - bossHurtReduce).divide(BigDecimal.valueOf(1000)))
                .setScale(0, BigDecimal.ROUND_UP).intValue();
        return value;
    }

    public int addSkillId(int skillId) {
        for (List<Integer> skill : skills) {
            int findId = skill.get(0);
            int skillLv = skill.get(1);
            if (findId == skillId) {
                skill.set(1, skillLv + 1);
                return skillLv + 1;
            }
        }

        skills.add(new ArrayList<Integer>() {{
            add(skillId);
            add(1);
        }});
        return 1;
    }

    /**
     * 计算技能伤害
     *
     * @param skillValue
     * @return
     */
    public int calcSkillDamage(int skillValue, int specialSkillAdd, int combMulti) {
        if (skillValue == 0) {
            return 0;
        }
        Integer atk = attrMap.get(eHotpotJumpAttr.Atk);
        Integer atkMulti = attrMap.getOrDefault(eHotpotJumpAttr.AtkMulti, 0);
        Integer damageMulti = attrMap.getOrDefault(eHotpotJumpAttr.DamageMulti, 0);

        int damage = BigDecimal.valueOf(atk).multiply(BigDecimal.valueOf(1000 + atkMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(combMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(skillValue).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 + damageMulti).divide(BigDecimal.valueOf(1000)))
                .multiply(BigDecimal.valueOf(1000 + specialSkillAdd).divide(BigDecimal.valueOf(1000)))
                .setScale(0, BigDecimal.ROUND_UP).intValue();
        return damage;
    }

    public int calcHurtReflect(int hurtValue) {
        Integer reflectRate = attrMap.getOrDefault(eHotpotJumpAttr.HurtReflect, 0);
        if (reflectRate == 0) {
            return 0;
        }
        return BigDecimal.valueOf(hurtValue).multiply(BigDecimal.valueOf(reflectRate).divide(BigDecimal.valueOf(1000))).setScale(0, BigDecimal.ROUND_UP).intValue();
    }

    public int calcBloodSucking(int realDamage) {
        Integer bloodSucking = attrMap.getOrDefault(eHotpotJumpAttr.BloodSucking, 0);
        if (bloodSucking == 0) {
            return 0;
        }
        return BigDecimal.valueOf(realDamage).multiply(BigDecimal.valueOf(bloodSucking).divide(BigDecimal.valueOf(1000))).setScale(0, BigDecimal.ROUND_UP).intValue();
    }

    public int findSkillLv(int skillId) {
        for (List<Integer> skill : skills) {
            int findId = skill.get(0);
            int skillLv = skill.get(1);
            if (findId == skillId) {
                return skillLv;
            }
        }
        return 0;
    }

    /**
     * 剩余血量千分比
     * @return
     */
    public int calcRemainHpRate() {
        int result = BigDecimal.valueOf(grid.getHp() * 1000).divide(BigDecimal.valueOf(grid.getHpMax()), 8, RoundingMode.DOWN).setScale(0, RoundingMode.UP).intValue();
        return result;
    }
}
